import { ActionContext } from 'vuex';
import cloneDeep from 'lodash/cloneDeep';
import { getFormData } from '@/core/api';
import eventBus from '@/core/eventBus';
import { FlowNode, ControlPproperty } from '@/model/types/formCard';
import { FlowProperty } from '@/model/designer/controlProperty';
import { ResponseHandle } from '@/global/util/preUtils';
import {
  openFlow,
  getFlowDefine,
  saveFlow,
  closeFlow,
} from '@/views/flowDesign/api';
import {
  InitFlowNodesData,
  InitFlowEdgesData,
} from '@/views/flowDesign/constant';

interface State {
  flowId: string;
  flowOpened: boolean;
  curNodeId: string;
  nodes: { [key: string]: any };
  edges: [];
  flowProperty: { [key: string]: any };
  form: { [key: string]: any };
  isLoading: boolean;
}
const getInitData = (): State => {
  return {
    flowId: '',
    flowOpened: false,
    curNodeId: '',
    edges: cloneDeep(InitFlowEdgesData),
    nodes: cloneDeep(InitFlowNodesData),
    flowProperty: cloneDeep(FlowProperty),
    form: {},
    isLoading: false,
  };
};

const state: State = getInitData();
const getters = {
  curNode: (state: State) => {
    return state.nodes.find((it: FlowNode) => it.id === state.curNodeId);
  },
};
const actions = {
  async getFormData(context: ActionContext<State, any>, schemaCode: string) {
    const res: any = await getFormData({ schemaCode });
    ResponseHandle(res, () => {
      res.data && context.commit('SetForm', res.data);
      if (res.data.flowId) {
        context.dispatch('getFlowDefine', res.data.flowId);
      }
    });
  },
  async getFlowDefine(context: ActionContext<State, any>, flowId: string) {
    const res: any = await getFlowDefine({ flowId });
    ResponseHandle(res, () => {
      res.data && context.commit('SetFlow', res.data);
    });
  },
  async openFlow(context: ActionContext<State, any>, schemaCode: string) {
    const params = {
      schemaCode,
      flowId: state.flowId,
    };
    if (!state.flowId) {
      context.commit('SetNodeEdge', {
        edges: cloneDeep(InitFlowEdgesData),
        nodes: cloneDeep(InitFlowNodesData),
      });
      Object.assign(params, {
        defineData: {
          edges: state.edges,
          nodes: state.nodes,
          flowProperty: state.flowProperty,
        },
      });
    }
    const res: any = await openFlow(params);
    ResponseHandle(res, () => {
      if (res.data) {
        context.commit('SetFlowId', res.data.flowId);
        context.commit('SetFlowOpened', res.data.flowOpened);
      }
    });
  },
  async closeFlow(context: ActionContext<State, any>) {
    const res: any = await closeFlow({ schemaCode: state.form.schemaCode });
    ResponseHandle(res, () => {
      context.commit('SetFlowOpened', false);
    });
  },
  async saveFlow(context: ActionContext<State, any>) {
    const defineData = {
      edges: state.edges,
      nodes: state.nodes,
      flowProperty: state.flowProperty,
    };
    const res: any = await saveFlow({ defineData, flowId: state.flowId });
    return res;
  },
};
const mutations = {
  SetIsLoading(state: State, data: boolean) {
    state.isLoading = data;
  },
  SetForm(state: State, data: any) {
    state.form = data;
    state.flowId = data.flowId;
    state.flowOpened = data.flowOpened;
  },
  SetFlow(state: State, data: any) {
    if (data.defineData) {
      state.edges = data.defineData.edges || [];
      state.nodes = data.defineData.nodes || [];
      state.flowProperty = data.defineData.flowProperty || {};
      eventBus.emit('flow-define-refresh');
    }
  },
  SetNodeEdge(state: State, data: any) {
    state.edges = data.edges;
    // 因为logicFlow node里的properties和state node里的不同步，所以只能同步properties以外的属性
    state.nodes = state.nodes.map((item: any) => {
      const origin = data.nodes.find((it: any) => it.id === item.id);
      Object.keys(item).forEach((key: string) => {
        if (key !== 'properties' && origin) {
          item[key] = origin[key];
        }
      });
      return item;
    });
  },
  SetFlowId(state: State, data: string) {
    state.flowId = data;
  },
  SetFlowOpened(state: State, data: boolean) {
    state.flowOpened = data;
  },
  SetCurNodeId(state: State, id: string) {
    state.curNodeId = id;
  },
  SetNodes(state: State, data: any) {
    state.nodes = data;
  },
  SetEdges(state: State, data: any) {
    state.edges = data;
  },
  setNodeName(state: State, data: { id: string; value: string }) {
    for (let i = 0; i < state.nodes.length; i++) {
      const el = state.nodes[i];
      if (el.id === data.id) {
        el.properties.nodeName.defaultValue = data.value;
        break;
      }
    }
  },
};
export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters,
};
